package main

import (
	"fmt"
	"log"
	"os"
	"os/signal"
	"path/filepath"
	"syscall"
	"time"

	"github.com/louloulin/dataflare/pkg/plugin/dependency"
	"github.com/louloulin/dataflare/pkg/plugin/hotload"
	"github.com/louloulin/dataflare/pkg/plugin/version"
)

// PluginEventHandler 插件事件处理器
type PluginEventHandler struct{}

// HandlePluginLoadEvent 处理插件加载事件
func (h *PluginEventHandler) HandlePluginLoadEvent(event hotload.PluginLoadEvent, plugin *hotload.PluginInfo, err error) {
	if err != nil {
		log.Printf("Plugin event %s for %s: ERROR - %v", event.String(), plugin.ID, err)
	} else {
		log.Printf("Plugin event %s for %s (version: %s)", event.String(), plugin.ID, plugin.Version)
	}
}

func main() {
	// 创建工作目录
	workDir, err := os.MkdirTemp("", "plugin-example")
	if err != nil {
		log.Fatalf("Failed to create work directory: %v", err)
	}
	defer os.RemoveAll(workDir)

	// 创建插件目录和元数据目录
	pluginsDir := filepath.Join(workDir, "plugins")
	metadataDir := filepath.Join(workDir, "metadata")
	err = os.MkdirAll(pluginsDir, 0755)
	if err != nil {
		log.Fatalf("Failed to create plugins directory: %v", err)
	}
	err = os.MkdirAll(metadataDir, 0755)
	if err != nil {
		log.Fatalf("Failed to create metadata directory: %v", err)
	}

	// 创建插件版本管理器
	versionManager, err := version.NewPluginVersionManager(pluginsDir, metadataDir, "1.0.0", "1.0.0")
	if err != nil {
		log.Fatalf("Failed to create plugin version manager: %v", err)
	}

	// 初始化版本管理器
	err = versionManager.Initialize()
	if err != nil {
		log.Fatalf("Failed to initialize plugin version manager: %v", err)
	}

	// 创建依赖解析器
	dependencyResolver := dependency.NewDependencyResolver()

	// 创建插件热加载器
	hotLoader, err := hotload.NewPluginHotLoader(pluginsDir, []hotload.PluginSymbol{"Initialize", "Shutdown"})
	if err != nil {
		log.Fatalf("Failed to create plugin hot loader: %v", err)
	}

	// 添加事件处理器
	hotLoader.AddEventHandler(&PluginEventHandler{})

	// 启动热加载器
	err = hotLoader.Start()
	if err != nil {
		log.Fatalf("Failed to start plugin hot loader: %v", err)
	}
	defer hotLoader.Stop()

	// 创建示例插件元数据
	plugin1Metadata := &version.PluginMetadata{
		ID:              "plugin1",
		Name:            "Plugin 1",
		Version:         "1.0.0",
		Description:     "Example plugin 1",
		Author:          "Example Author",
		License:         "MIT",
		Dependencies:    make(map[string]string),
		EntryPoint:      "Initialize",
		Tags:            []string{"example"},
		TargetPlatforms: []string{"linux", "windows"},
		MinHostVersion:  "1.0.0",
		MaxHostVersion:  "2.0.0",
		PluginAPIVersion: "1.0.0",
		FilePath:        filepath.Join(pluginsDir, "plugin1-1.0.0.so"),
	}

	plugin2Metadata := &version.PluginMetadata{
		ID:              "plugin2",
		Name:            "Plugin 2",
		Version:         "1.0.0",
		Description:     "Example plugin 2",
		Author:          "Example Author",
		License:         "MIT",
		Dependencies:    map[string]string{"plugin1": ">=1.0.0"},
		EntryPoint:      "Initialize",
		Tags:            []string{"example"},
		TargetPlatforms: []string{"linux", "windows"},
		MinHostVersion:  "1.0.0",
		MaxHostVersion:  "2.0.0",
		PluginAPIVersion: "1.0.0",
		FilePath:        filepath.Join(pluginsDir, "plugin2-1.0.0.so"),
	}

	// 注册插件元数据
	log.Println("Registering plugin metadata...")
	err = versionManager.RegisterPlugin(plugin1Metadata)
	if err != nil {
		log.Printf("Failed to register plugin1: %v", err)
	}
	err = versionManager.RegisterPlugin(plugin2Metadata)
	if err != nil {
		log.Printf("Failed to register plugin2: %v", err)
	}

	// 添加插件到依赖解析器
	dependencyResolver.AddPlugin(&dependency.Plugin{
		ID:           plugin1Metadata.ID,
		Version:      plugin1Metadata.Version,
		Dependencies: plugin1Metadata.Dependencies,
	})
	dependencyResolver.AddPlugin(&dependency.Plugin{
		ID:           plugin2Metadata.ID,
		Version:      plugin2Metadata.Version,
		Dependencies: plugin2Metadata.Dependencies,
	})

	// 解析依赖
	log.Println("Resolving dependencies...")
	deps, err := dependencyResolver.ResolveDependencies("plugin2", "1.0.0")
	if err != nil {
		log.Printf("Failed to resolve dependencies: %v", err)
	} else {
		log.Printf("Dependencies for plugin2: %d plugins", len(deps))
		for i, dep := range deps {
			log.Printf("  %d. %s@%s", i+1, dep.ID, dep.Version)
		}
	}

	// 创建示例插件文件
	log.Println("Creating example plugin files...")
	err = createDummyPluginFile(filepath.Join(pluginsDir, "plugin1-1.0.0.so"))
	if err != nil {
		log.Printf("Failed to create plugin1 file: %v", err)
	}
	err = createDummyPluginFile(filepath.Join(pluginsDir, "plugin2-1.0.0.so"))
	if err != nil {
		log.Printf("Failed to create plugin2 file: %v", err)
	}

	// 等待文件系统事件
	log.Println("Waiting for file system events...")
	time.Sleep(time.Second)

	// 获取所有插件
	log.Println("Getting all plugins...")
	plugins := versionManager.GetAllPlugins()
	for id, versions := range plugins {
		log.Printf("Plugin %s: %d versions", id, len(versions))
		for _, p := range versions {
			log.Printf("  - %s: %s", p.Version, p.Description)
		}
	}

	// 获取活动版本
	log.Println("Getting active versions...")
	for id := range plugins {
		version, err := versionManager.GetActiveVersion(id)
		if err != nil {
			log.Printf("Failed to get active version for %s: %v", id, err)
		} else {
			log.Printf("Active version for %s: %s", id, version)
		}
	}

	// 创建新版本
	log.Println("Creating new plugin version...")
	plugin1v2Metadata := &version.PluginMetadata{
		ID:              "plugin1",
		Name:            "Plugin 1",
		Version:         "2.0.0",
		Description:     "Example plugin 1 version 2",
		Author:          "Example Author",
		License:         "MIT",
		Dependencies:    make(map[string]string),
		EntryPoint:      "Initialize",
		Tags:            []string{"example"},
		TargetPlatforms: []string{"linux", "windows"},
		MinHostVersion:  "1.0.0",
		MaxHostVersion:  "2.0.0",
		PluginAPIVersion: "1.0.0",
		FilePath:        filepath.Join(pluginsDir, "plugin1-2.0.0.so"),
	}

	// 注册新版本
	err = versionManager.RegisterPlugin(plugin1v2Metadata)
	if err != nil {
		log.Printf("Failed to register plugin1 v2: %v", err)
	}

	// 添加新版本到依赖解析器
	dependencyResolver.AddPlugin(&dependency.Plugin{
		ID:           plugin1v2Metadata.ID,
		Version:      plugin1v2Metadata.Version,
		Dependencies: plugin1v2Metadata.Dependencies,
	})

	// 创建新版本文件
	err = createDummyPluginFile(filepath.Join(pluginsDir, "plugin1-2.0.0.so"))
	if err != nil {
		log.Printf("Failed to create plugin1 v2 file: %v", err)
	}

	// 等待文件系统事件
	time.Sleep(time.Second)

	// 获取最新版本
	log.Println("Getting latest versions...")
	for id := range plugins {
		version, err := versionManager.GetLatestVersion(id)
		if err != nil {
			log.Printf("Failed to get latest version for %s: %v", id, err)
		} else {
			log.Printf("Latest version for %s: %s", id, version)
		}
	}

	// 设置活动版本
	log.Println("Setting active version...")
	err = versionManager.SetActiveVersion("plugin1", "2.0.0")
	if err != nil {
		log.Printf("Failed to set active version: %v", err)
	}

	// 获取活动版本
	log.Println("Getting active versions after update...")
	for id := range plugins {
		version, err := versionManager.GetActiveVersion(id)
		if err != nil {
			log.Printf("Failed to get active version for %s: %v", id, err)
		} else {
			log.Printf("Active version for %s: %s", id, version)
		}
	}

	// 解析依赖
	log.Println("Resolving dependencies after update...")
	deps, err = dependencyResolver.ResolveDependencies("plugin2", "1.0.0")
	if err != nil {
		log.Printf("Failed to resolve dependencies: %v", err)
	} else {
		log.Printf("Dependencies for plugin2: %d plugins", len(deps))
		for i, dep := range deps {
			log.Printf("  %d. %s@%s", i+1, dep.ID, dep.Version)
		}
	}

	// 等待信号
	log.Println("Plugin system example running. Press Ctrl+C to stop.")
	sigCh := make(chan os.Signal, 1)
	signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
	<-sigCh
	log.Println("Shutting down...")
}

// createDummyPluginFile 创建虚拟插件文件
func createDummyPluginFile(path string) error {
	// 创建目录
	dir := filepath.Dir(path)
	err := os.MkdirAll(dir, 0755)
	if err != nil {
		return fmt.Errorf("failed to create directory: %w", err)
	}

	// 创建文件
	file, err := os.Create(path)
	if err != nil {
		return fmt.Errorf("failed to create file: %w", err)
	}
	defer file.Close()

	// 写入内容
	_, err = file.WriteString("dummy plugin")
	if err != nil {
		return fmt.Errorf("failed to write file: %w", err)
	}

	return nil
}
